﻿using System;
using System.Linq;
using System.Windows;

using SimbaRGVMonitor.Models;

namespace SimbaRGVMonitor.Views.Components
{
    partial class MonitorScheduleCanvas
    {
        internal void AddVertex(Vertex vertex)
        {
            VertexItem vertexItem;
            if (CreateVertexItem(vertex, out vertexItem))
            {
                vertexItems.Add(vertexItem.VertexNo, vertexItem);
                canvas.Children.Add(vertexItem);
            }

            SetScrollMinSize();
        }

        internal void UpdateVertex(Vertex vertex)
        {
            Point newLocation;
            var vertexNo = vertex.VertexNo;
            var orginalItem = vertexItems[vertexNo];
            if (CalculateVertexLocation(orginalItem, vertex, out newLocation))
            {
                orginalItem.ResetVertex(vertex, newLocation);
            }

            SetScrollMinSize();
        }

        internal void RemoveVertex(string vertexNo)
        {
            var item = vertexItems[vertexNo];
            vertexItems.Remove(vertexNo);
            canvas.Children.Remove(item);

            SetScrollMinSize();
        }

        internal void ResetVertexes(Vertex[] vertexes)
        {
            var orginalKeys = vertexItems.Keys;
            var newKeys = vertexes.Select(item => item.VertexNo).ToArray();

            var removeKeys = orginalKeys.Except(newKeys).ToArray();
            var addKeys = newKeys.Except(vertexItems.Keys).ToArray();
            var updateKeys = newKeys.Intersect(vertexItems.Keys).ToArray();
            
            foreach (var key in removeKeys)
            {
                RemoveVertex(key);
            }

            foreach (var key in addKeys)
            {
                var vertex = vertexes.First(item => item.VertexNo == key);
                AddVertex(vertex);
            }

            foreach(var key in updateKeys)
            {
                var vertex = vertexes.First(item => item.VertexNo == key);
                UpdateVertex(vertex);
            }
        }

        private bool CreateVertexItem(Vertex vertex, out VertexItem vertexItem)
        {
            Point location;
            vertexItem = new VertexItem { Width = 60, Height = 80, Opacity = 0.5 };
            if(CalculateVertexLocation(vertexItem, vertex, out location) == false)
            {
                vertexItem = null;
                return false;
            }
            vertexItem.ResetVertex(vertex, location);
            return true;
        }

        private bool CalculateVertexLocation(VertexItem vertexItem, Vertex vertex, out Point location)
        {
            if(canvas.HasActualHeight() == false)
            {
                location = new Point();
                return false;
            }

            var x = MapLeft + Math.Round(vertex.PositionX * MapHRate, 2);
            var y = canvas.ActualHeight - MapTop - Math.Round(vertex.PositionY * MapVRate, 2);
            location = new Point(x, y);
            return true;
        }
    }
}
